/**
 * Copyright (c) 2017,安徽皖通科技股份有限公司 All rights reserved.
 *
 * @data:2017年10月12日
 * @author:MaShibo
 */
package com.wttech.dzzf.process.service;

import cn.com.taiji.sdk.model.comm.protocol.AbstractSdtsRequest;
import com.wttech.dzzf.process.constant.ExecuteTable;
import com.wttech.dzzf.process.dao.TransferUserInfoDao;
import com.wttech.dzzf.process.service.user.UserDetailInfosCreatorService;
import com.wttech.dzzf.process.util.GenerateJsonFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * 生成客户、车辆、卡、OBUJson文件
 *
 * @author MaShibo
 * @date 2017年10月12日
 */
@Service
public class CommonConsumerService {


    private static final Logger LOGGER = LoggerFactory.getLogger(CommonConsumerService.class);

    private static final Object LOCK = new Object();

    /**
     * 每次处理数量
     */
    private static final int DEFAULT_PROCESS_NUM = 10000;

    private List<ExecuteTable> executeTables;

    @Resource
    private ThreadPoolTaskExecutor executor;

    @Resource
    private TransferUserInfoDao transferUserInfoDao;

    @Resource
    private UserDetailInfosCreatorService userDetailInfosCreatorService;


    /**
     * 异步生成Json自测文件
     */
    private void asyncCreateJsonFiles() {
        if (CollectionUtils.isEmpty(executeTables)) {
            executeTables = Arrays.asList(ExecuteTable.values());
        }
        LOGGER.info("共{}项数据待生成", executeTables.size());
        for (ExecuteTable table : executeTables) {
            String tableName = table.getTableName();
            LOGGER.info("开始生成【{}】表数据", tableName);
            Integer total = transferUserInfoDao.queryUserInfoCount(tableName);
            LOGGER.info("{}共{}条数据待处理...", tableName, total);
            int count = (int) Math.ceil((double) total / DEFAULT_PROCESS_NUM);
            LOGGER.info("共需处理{}次", count);
            List<Future<Void>> futures = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                futures.add(executor.submit(new SubProcessJsonFile(table, i + 1)));
            }
            userDetailInfosCreatorService.getFutureResult(futures);
        }
        executor.shutdown();
    }

    public List<ExecuteTable> getExecuteTables() {
        return executeTables;
    }

    private void setExecuteTables(List<ExecuteTable> executeTables) {
        this.executeTables = executeTables;
    }

    public class SubProcessJsonFile implements Callable<Void> {

        private ExecuteTable executeTable;
        private int count;

        SubProcessJsonFile(ExecuteTable executeTable, int count) {
            this.executeTable = executeTable;
            this.count = count;
        }

        @Override
        public Void call() throws Exception {
            LOGGER.info("第{}次开始执行...", count);
            int startRow = (count - 1) * DEFAULT_PROCESS_NUM + 1;
            int endRow = count * DEFAULT_PROCESS_NUM;
            List<? extends AbstractSdtsRequest> infos = transferUserInfoDao.queryUseriInfoRecord(executeTable.getTableName(), executeTable.getRequestType(),
                    startRow, endRow);
            synchronized (LOCK) {
                try {
                    TimeUnit.MICROSECONDS.sleep(2);
                } catch (InterruptedException e) {
                    LOGGER.error(e.getMessage(), e);
                    Thread.currentThread().interrupt();
                }
                GenerateJsonFile.generateJsonFile(infos, executeTable.getStorePath());
            }
            LOGGER.info("第{}次结束执行..", count);
            return null;
        }
    }

    public static void main(String[] args) {
        @SuppressWarnings("resource")
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        CommonConsumerService service = context.getBean(CommonConsumerService.class);
        if (args.length > 0){
            List<ExecuteTable> tables = new ArrayList<>(args.length);
            Arrays.stream(ExecuteTable.values()).forEach(table -> Arrays.stream(args).forEach(arg -> {
                if (table.getStorePath().equals(arg)){
                    tables.add(table);
                }
            }));
            service.setExecuteTables(tables);
        }
        service.asyncCreateJsonFiles();
    }
}
